package com.tian.mybatis.session;

import com.tian.mybatis.annotation.Param;
import com.tian.mybatis.config.Configuration;
import com.tian.mybatis.config.MapperStatement;
import com.tian.mybatis.executor.SimpleExecutor;

import java.lang.reflect.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author tianwc  公众号：java后端技术全栈、面试专栏
 * @version 1.0.0
 * @date 2023年09月21日 15:40
 * 在线刷题 1200+题和1000+篇干货文章：<a href="https://woaijava.cc/">博客地址</a>
 * <p>
 * SqLSession 默认实现类
 */
public class DefaultSqlSession implements SqlSession {

    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <E> List<E> selectList(String statementId, Object... params) throws Exception {
        System.out.println("查询多条");
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        return simpleExecutor.doQuery(configuration, mapperStatement, params);
    }

    @Override
    public <E> E selectOne(String statementId, Object... params) throws Exception {
        System.out.println("查询单条");
        List<Object> objectList = this.selectList(statementId, params);
        if (objectList.size() == 0) {
            throw new RuntimeException("没有查询到数据");
        }
        return (E) objectList.get(0);
    }

    @Override
    public <E> E insert(String statementId, Object... params) throws Exception {
        System.out.println("新增");
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        return simpleExecutor.doUpdate(configuration, mapperStatement, params);
    }

    @Override
    public <E> E update(String statementId, Object... params) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        return simpleExecutor.doUpdate(configuration, mapperStatement, params);
    }

    @Override
    public <E> E dalete(String statementId, Object... params) throws Exception {
        System.out.println("删除");
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        return simpleExecutor.doUpdate(configuration, mapperStatement, params);
    }

    /**
     * 使用JDK动态代理给UserMapper接口生一个实现类
     *
     * @param mapperClass UserMapper.class
     * @param <T>
     * @return
     */
    @Override
    public <T> T getMapper(Class<T> mapperClass) {
        Object instance = Proxy.newProxyInstance(mapperClass.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //调用的方法名称
                String methodName = method.getName();
                //这个方法背定义在哪个接口中
                String className = method.getDeclaringClass().getName();
                //拼接SQL的唯一标识
                String statementId = className + "." + methodName;
                //获取方法调用之后的返回值类型（方法返回类型）
                Type genericReturnType = method.getGenericReturnType();

                Map<String, MapperStatement> mapperStatementMap = configuration.getMapperStatementMap();
                MapperStatement mapperStatement = mapperStatementMap.get(statementId);
                String sqlType = mapperStatement.getSqlType();
                if (sqlType.equals("update")) {
                    return update(statementId, args);
                } else if (sqlType.equals("insert")) {
                    return insert(statementId, args);
                } else if (sqlType.equals("dalete")) {
                    return dalete(statementId, args);
                }


                /*Map<String, Object> paramValueMapping = new HashMap<>();
                Parameter[] parameters = method.getParameters();

                for (int i = 0; i < parameters.length; i++) {
                    Parameter parameter = parameters[i];
                    String name = parameter.getAnnotation(Param.class).value();
                    paramValueMapping.put(parameter.getName(), args[i]);
                    paramValueMapping.put(name, args[i]);
                }
*/

                //表示我们查询返回的是否是泛型类型的参数化
                if (genericReturnType instanceof ParameterizedType) {
                    return selectList(statementId, args);
                } else {
                    //查询结果不是泛型
                    return selectOne(statementId, args);
                }
            }
        });
        return (T) instance;
    }
}
